import SwiftUI
import Metal
import MetalKit
import AVFoundation

// SwiftUI视图封装
struct MetalVideoPlayerView: UIViewRepresentable {
    // 视频文件名称（不带扩展名）
    var videoName: String
    @EnvironmentObject var vm: PlayerViewModel  // 接收视图模型
    
    // 1. 创建协调器（用于SwiftUI与UIKit通信）
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    // 4. 协调器类（处理交互逻辑）
    class Coordinator: NSObject {
        var parent: MetalVideoPlayerView
        weak var playerView: MetalPlayerView?
        
        init(_ parent: MetalVideoPlayerView) {
            self.parent = parent
            super.init()
        }
        
        // 封装播放控制方法
        func play() {
            playerView?.play()
        }
        
        func pause() {
            playerView?.pause()
        }
    }
    
    func makeUIView(context: Context) -> MetalPlayerView {
        let playerView = MetalPlayerView(frame: .zero)
        playerView.loadVideo(named: videoName)
        
        // 关键：将 playerView 赋值给协调器的 playerView 属性
        context.coordinator.playerView = playerView  // 新增这一行
        
        // 绑定协调器到视图模型
        vm.coordinator = context.coordinator

        
        return playerView
    }
    
    func updateUIView(_ uiView: MetalPlayerView, context: Context) {
        // 更新逻辑（如尺寸变化处理）
        uiView.frame = uiView.superview?.bounds ?? .zero
    }
}

// Metal渲染视图
class MetalPlayerView: UIView {

    private var metalLayer: CAMetalLayer!
    
    private var processor: MetalMp4Processor!
    private var combileProcessor: MetalCombinedImageProcessor!
    
    // 视频解码相关属性
    private var asset: AVAsset!
    private var playerItem: AVPlayerItem!
    private var player: AVPlayer!
    private var videoOutput: AVPlayerItemVideoOutput!
    private var displayLink: CADisplayLink!
    private var textureCache: CVMetalTextureCache!
    
    override class var layerClass: AnyClass {
        return CAMetalLayer.self
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
//        self.isOpaque = false
//        self.backgroundColor = UIColor.green  // 背景色设为透明
        
        setupMetal()
        setupVideoOutput()
        setupDisplayLink()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // 初始化Metal环境
    private func setupMetal() {
    
        // 创建处理器并处理图片
        processor = MetalMp4Processor()
        combileProcessor = MetalCombinedImageProcessor()
        
        // 配置Metal图层
        metalLayer = layer as? CAMetalLayer
        metalLayer?.device = processor.device
        metalLayer?.device = combileProcessor.device
        metalLayer?.pixelFormat = .bgra8Unorm
        metalLayer?.framebufferOnly = true
        metalLayer.isOpaque = false
//        metalLayer.backgroundColor = UIColor.clear.cgColor
        
    }
    
    // 初始化视频输出
    private func setupVideoOutput() {
        let pixelBufferAttributes: [String: Any] = [
            kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA,
            kCVPixelBufferMetalCompatibilityKey as String: true
        ]
        
        videoOutput = AVPlayerItemVideoOutput(pixelBufferAttributes: pixelBufferAttributes)
        
        // 创建纹理缓存
        CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, processor.device, nil, &textureCache)
    }
    
    // 初始化显示链路（与屏幕刷新率同步）
    private func setupDisplayLink() {
        displayLink = CADisplayLink(target: self, selector: #selector(renderFrame))
        displayLink.add(to: .main, forMode: .common)
    }
    
    // 加载视频文件
    func loadVideo(named name: String) {
        guard let url = Bundle.main.url(forResource: name, withExtension: "mp4") else {
            fatalError("无法找到视频文件: \(name).mp4")
        }
        
        asset = AVAsset(url: url)
        playerItem = AVPlayerItem(asset: asset)
        playerItem.add(videoOutput)
        
        player = AVPlayer(playerItem: playerItem)
    }
    
    // 开始播放
    func play() {
        
        let interval = CMTimeMakeWithSeconds(1.0, preferredTimescale: 600)
        player.seek(to: interval)
        player.play()
    }
    
    // 暂停播放
    func pause() {
        player.pause()
    }
    
    // 渲染每一帧
    @objc private func renderFrame() {
        guard playerItem.status == .readyToPlay else { return }
        
        let currentTime = videoOutput.itemTime(forHostTime: CACurrentMediaTime())
        guard videoOutput.hasNewPixelBuffer(forItemTime: currentTime) else { return }
        
        // 获取视频帧
        var pixelBuffer: CVPixelBuffer?
        pixelBuffer = videoOutput.copyPixelBuffer(forItemTime: currentTime, itemTimeForDisplay: nil)
        
        guard let buffer = pixelBuffer else { return }
        
        // 将CVPixelBuffer转换为Metal纹理
        let width = CVPixelBufferGetWidth(buffer)
        let height = CVPixelBufferGetHeight(buffer)
        
        var metalTexture: CVMetalTexture?
        let result = CVMetalTextureCacheCreateTextureFromImage(
            kCFAllocatorDefault,
            textureCache,
            buffer,
            nil,
            .bgra8Unorm,
            width,
            height,
            0,
            &metalTexture
        )
        
        guard result == kCVReturnSuccess, let texture = CVMetalTextureGetTexture(metalTexture!) else {
            return
        }
        // 准备渲染命令
        guard let drawable = metalLayer?.nextDrawable() else { return }
        
//        processor.process(mtlTexture: texture, drawable: drawable)
        
        
        combileProcessor.process(
            combinedTexture: texture,
            maskPosition: .rightHalf,
            drawable: drawable
        ) 
        
        
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        metalLayer?.frame = bounds
        metalLayer?.drawableSize = bounds.size
    }
}

// SwiftUI使用示例
struct MetalPlayerDemoView: View {
    // 使用 @StateObject 或 @ObservedObject 管理播放器状态（更优雅的方式）
    private let playerViewModel = PlayerViewModel()
    
    var body: some View {
        VStack {
            Text("Metal MP4播放器")
                .font(.title)
                .padding()
            
            MetalVideoPlayerView(videoName: "sample") // 确保项目中有sample.mp4文件
                .frame(height: 520)
                .background(Image("jimeng"))
                .environmentObject(playerViewModel)  // 传递视图模型
            
            HStack {
                Button("播放") {
                    // 获取MetalPlayerView实例并调用play()
                    // 在实际项目中可以通过协调器(Coordinator)实现
                    playerViewModel.play()
                }
                .padding()
                .background(Color.blue)
                .foregroundColor(.white)
                .cornerRadius(8)
                
                Button("暂停") {
                    // 类似播放按钮的实现
                    playerViewModel.pause()
                }
                .padding()
                .background(Color.gray)
                .foregroundColor(.white)
                .cornerRadius(8)
            }
        }
    }
}

// 新增：用视图模型统一管理播放状态（解耦UI与逻辑）
class PlayerViewModel: ObservableObject {
    weak var coordinator: MetalVideoPlayerView.Coordinator?
    
    func play() {
        coordinator?.play()
    }
    
    func pause() {
        coordinator?.pause()
    }
}

// 预览
struct MetalPlayerDemoView_Previews: PreviewProvider {
    static var previews: some View {
        MetalPlayerDemoView()
    }
}
